﻿#include "WavesRenderPass.h"

#include "../../../Common/Singleton.h"
#include "../ResourceManager/Dx2GeometryManager.h"
#include "../ResourceManager/Dx2MaterialManager.h"
#include "../ResourceManager/Dx2RootSignatureManager.h"
#include "../ResourceManager/Dx2ShaderAndLayoutManager.h"

void WavesRenderPass::BuildRenderItems(std::vector<std::unique_ptr<RenderItem>>& allRitems,UINT& lastObjIndex)
{
    auto wavesRitem = std::make_unique<RenderItem>();
    wavesRitem->World = MathHelper::Identity4x4();
    XMStoreFloat4x4(&wavesRitem->TexTransform, DirectX::XMMatrixScaling(5.0f, 5.0f, 1.0f));
    wavesRitem->DisplacementMapTexelSize.x = 1.0f /mWaves->RowCount();
    wavesRitem->DisplacementMapTexelSize.y = 1.0f /mWaves->ColumnCount();
    wavesRitem->GridSpatialStep = mWaves->SpatialStep();
    wavesRitem->ObjCBIndex = lastObjIndex;
    lastObjIndex++;
    wavesRitem->Mat = Singleton<Dx2MaterialManager>::Instance()->GetMaterial("water").get();
    wavesRitem->Geo = Singleton<Dx2GeometryManager>::Instance()->GetGeometry("waterGeo").get();
    wavesRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
    wavesRitem->IndexCount = wavesRitem->Geo->DrawArgs["grid"].IndexCount;
    wavesRitem->StartIndexLocation = wavesRitem->Geo->DrawArgs["grid"].StartIndexLocation;
    wavesRitem->BaseVertexLocation = wavesRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
	
    mRenderItems.push_back(wavesRitem.get());
    allRitems.push_back(move(wavesRitem));
}

void WavesRenderPass::BuildPSOs(
    ID3D12Device* device,
    DXGI_FORMAT BackBufferFormat, DXGI_FORMAT DepthStencilFormat,
    bool _4xMsaaState, UINT _4xMsaaQuality)
{
    D3D12_GRAPHICS_PIPELINE_STATE_DESC wavesRenderPSODesc;
    ZeroMemory(&wavesRenderPSODesc,sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
	
    wavesRenderPSODesc.InputLayout = {Singleton<Dx2ShaderAndLayoutManager>::Instance()->GetInputLayout().data(),(UINT)Singleton<Dx2ShaderAndLayoutManager>::Instance()->GetInputLayout().size()};
    wavesRenderPSODesc.pRootSignature = Singleton<Dx2RootSignatureManager>::Instance()->GetRootSignature(RootSignatureType::Default).Get();
	
    wavesRenderPSODesc.VS =
        {
        reinterpret_cast<BYTE*>(Singleton<Dx2ShaderAndLayoutManager>::Instance()->GetShader("wavesVS")->GetBufferPointer()),
        Singleton<Dx2ShaderAndLayoutManager>::Instance()->GetShader("wavesVS")->GetBufferSize()
    };
	
    wavesRenderPSODesc.PS =
        {
        reinterpret_cast<BYTE*>(Singleton<Dx2ShaderAndLayoutManager>::Instance()->GetShader("opaquePS")->GetBufferPointer()),
        Singleton<Dx2ShaderAndLayoutManager>::Instance()->GetShader("opaquePS")->GetBufferSize()
    };
	
    wavesRenderPSODesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
    wavesRenderPSODesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
    wavesRenderPSODesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
    wavesRenderPSODesc.SampleMask = UINT_MAX;
    wavesRenderPSODesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
    wavesRenderPSODesc.NumRenderTargets = 1;
    wavesRenderPSODesc.RTVFormats[0] = BackBufferFormat;
    wavesRenderPSODesc.SampleDesc.Count = _4xMsaaState? 4:1;
    wavesRenderPSODesc.SampleDesc.Quality = _4xMsaaState? (_4xMsaaQuality - 1):0;
    wavesRenderPSODesc.DSVFormat = DepthStencilFormat;
    
    D3D12_RENDER_TARGET_BLEND_DESC transparencyBlendDesc;
    transparencyBlendDesc.BlendEnable = true;
    transparencyBlendDesc.LogicOpEnable = false;
    transparencyBlendDesc.SrcBlend = D3D12_BLEND_SRC_ALPHA;
    transparencyBlendDesc.DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
    transparencyBlendDesc.BlendOp = D3D12_BLEND_OP_ADD;
    transparencyBlendDesc.SrcBlendAlpha = D3D12_BLEND_ONE;
    transparencyBlendDesc.DestBlendAlpha = D3D12_BLEND_ZERO;
    transparencyBlendDesc.BlendOpAlpha = D3D12_BLEND_OP_ADD;
    transparencyBlendDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
    transparencyBlendDesc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;

    wavesRenderPSODesc.BlendState.RenderTarget[0] = transparencyBlendDesc;
    ThrowIfFailed(device->CreateGraphicsPipelineState(&wavesRenderPSODesc,IID_PPV_ARGS(&mPso)));
}

void WavesRenderPass::Draw(
    ID3D12GraphicsCommandList* cmdList,
    CD3DX12_GPU_DESCRIPTOR_HANDLE hGpuHandler,
    UINT srvHeapSize,UINT objCBByteSize, UINT matCBByteSize, UINT passCBByteSize,
    ID3D12Resource* objectCB, ID3D12Resource* matCB, ID3D12Resource* passCB,
    const PassConstants& passValue,
    ID3D12Resource* OutColorRenderTarget,
    D3D12_CPU_DESCRIPTOR_HANDLE OutColorRenderTargetView,
    D3D12_CPU_DESCRIPTOR_HANDLE OutDepthStentilView
    )
{
    cmdList->SetPipelineState(mPso.Get());
    DrawRenderItem(
        cmdList,
        hGpuHandler,
        srvHeapSize,objCBByteSize,matCBByteSize,
        objectCB,matCB,
        mRenderItems);
}

void WavesRenderPass::SetCSWave(std::shared_ptr<GPUWaves> wave)
{
    mWaves = wave;
}


